package edu.whu;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author guanruwang
 * @date 2023/10/1$
 */
public class MyApplicationContext {
    private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();

    private Map<String, Object> beanMap = new HashMap<>();

    public MyApplicationContext(String configLocation) throws Exception {
        loadBeanDefinitions(configLocation);
    }

    public void loadBeanDefinitions(String configLocation) throws Exception {
        if (null == configLocation || configLocation.isEmpty()) {
            return;
        }
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(configLocation);

        // 读取 xml 文件的内容
        SAXReader saxReader = new SAXReader();
        Document document = saxReader.read(inputStream);
        // 获取根标签
        Element rootElement = document.getRootElement();

        List<Element> elements = rootElement.elements();
        // 循环所有的标签
        for (Element element : elements) {
            // 取出 id 属性和 class 属性
            String id = element.attributeValue("id");
            String clazz = element.attributeValue("class");

            BeanDefinition beanDefinition = new BeanDefinition();
            beanDefinition.setId(id);
            beanDefinition.setClassName(clazz);

            // 取出 property 标签
            List<Element> propertyElements = element.elements("property");
            for (Element propertyElement : propertyElements) {

                String name = propertyElement.attributeValue("name");
                String value = propertyElement.attributeValue("value");
                beanDefinition.addPropertyValues(new PropertyValue(name, value));
            }
            // 将 beanDefinition 对象放到 beanDefinitionRegistry 注册表对象中
            beanDefinitionMap.put(id, beanDefinition);
        }
    }

    public Object getBean(String name) throws Exception {
        // 先判断容器中是否存在该 bean 对象,存在就直接返回
        Object obj = beanMap.get(name);
        if (null != obj) {
            return obj;
        }

        BeanDefinition beanDefinition = beanDefinitionMap.get(name);
        if (null == beanDefinition) {
            return null;
        }

        // 通过反射创建bean
        Class<?> clazz = Class.forName(beanDefinition.getClassName());
        Object beanObj = clazz.newInstance();

        // 获取依赖信息
        List<PropertyValue> mutablePropertyValues = beanDefinition.getPropertyValues();
        for (PropertyValue mutablePropertyValue : mutablePropertyValues) {
            String propertyValueName = mutablePropertyValue.getName();
            String value = mutablePropertyValue.getValue();

            if (null != value && !value.isEmpty()) {
                Field declaredField = beanObj.getClass().getDeclaredField(propertyValueName);
                //将私有属性设置为可访问
                declaredField.setAccessible(true);

                String fieldTypeName = declaredField.getType().getName();
                Object o = ParamType(fieldTypeName, value);
                declaredField.set(beanObj, o);
            }
        }
        // 将创建出来的对象放入 ioc 容器中
        beanMap.put(name, beanObj);
        return beanObj;
    }

    private Object ParamType(String fieldTypeName, String value) {
        Object obj = null;
        //判断该成员属性是否为int或Integer类型
        if ("int".equals(fieldTypeName) || "java.lang.Integer".equals(fieldTypeName)) {
            //转换为int类型并为该成员属性赋值
            int intFieldValue = Integer.parseInt(value);
            obj = intFieldValue;

        }//判断该成员属性是否为String类型
        if ("java.lang.String".equals(fieldTypeName)) {
            //为该成员属性赋值
            obj = value;
        }

        return obj;
    }

}
